package com.panda.pojo;


import com.fasterxml.jackson.annotation.JsonIgnore;
import com.panda.utils.IdUtils;
import com.google.common.collect.Sets;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

//每个元素都有一个作用域
//每个作用域也都服务于一个元素

@Setter
@Getter
public class Scope implements Serializable {

    //父作用域
    @JsonIgnore
    private Scope parent;

    private Set<String> dependencies = Sets.newHashSet("$rootScope","$scope", "$compile", "$element");

    public void addDependence(String s) {
        dependencies.add(s);
    }


    private String id;

    @JsonIgnore
    private Element element;

    private Set<String> params = new HashSet<>();

    public Scope() {
    }

    Scope(Element element) {
        this.element = element;
        id = IdUtils.gCreate(element.getContext(), "scope_");
    }

    private String script;

    public void addParam(String key) {
        params.add(key);
    }

    //值的部分是作用域的深度
    private Map<String, Integer> allParams = null;

    public Map<String, Integer> getAllParams() {

        if (allParams == null) {
            allParams = new MyMap<>();
            deepParam(allParams, 0);
        }

        return allParams;
    }

    private void deepParam(Map<String, Integer> map, Integer d) {

        //如果当前不形成作用域,就移交给父作用域
        if (script == null || script.equals("")) {

            if (parent != null) {
                parent.deepParam(map, d);
            }

            return;
        }

        for (String param : params) {
            map.put(param, d);
        }

        if (parent != null) {
            parent.deepParam(map, d + 1);
        }

    }


    //拒绝新值加入
    private static class MyMap<T,S> extends HashMap<T,S> {
        @Override
        public S put(T key, S value) {

            if (containsKey(key)) {
                return get(key);
            }

            return super.put(key, value);
        }
    }


    private Set<String> realLocalParams = null;

    public Set<String> getLocalParams() {

        //递归找到有脚本的作用域
        if (script == null || script.equals("")) {

            if (realLocalParams != null) {
                return realLocalParams;
            }

            if (parent == null) {
                return null;
            }

            realLocalParams = parent.getLocalParams();

            return realLocalParams;

        }

        return params;
    }


}
